package com.my.netty.nio.net.nonblock;


import com.my.netty.nio.utils.ByteBufferUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class NonBlockNioServer {

    public static void main(String[] args) throws IOException {
        //NIO的非阻塞式TCP服务端（单线程处理，因为线程不会阻塞，可以同时处理多个客户端连接和读数据，但是导致CPU大量空转）
        ByteBuffer buf = ByteBuffer.allocate(16);

        //1.创建ServerSocketChannel
        ServerSocketChannel ssc = ServerSocketChannel.open();

        //2.监听8080端口，配置未非阻塞模式：accept()方法变为非阻塞
        ssc.configureBlocking(false);
        ssc.bind(new InetSocketAddress(8080));

        List<SocketChannel> socketChannels = new ArrayList<>();

        log.debug("等待连接...");
        //3.等待客户端连接
        while (true) {
            //log.debug("等待连接...");
            SocketChannel sc = ssc.accept(); //accept变为非阻塞的，没有客户端连接时返回空
            if (sc != null) {
                log.debug("获取连接：{}", sc.getRemoteAddress());

                //设置SocketChannel为非阻塞模式：read()方法变为非阻塞
                sc.configureBlocking(false);
                socketChannels.add(sc);
            }

            //4.接收每个客户端数据
            for (SocketChannel channel : socketChannels) {
                //log.debug("等待读取客户端数据... {}", channel.getRemoteAddress());
                int len = channel.read(buf);//read是非阻塞的，如果没有客户端发送数据，返回值为0
                if (len > 0) {
                    //切换为读模式
                    buf.flip();
                    //5.打印buffer内容
                    debugRead(buf);
                    //切换为写模式
                    buf.clear();
                    log.debug("读取客户端数据完成 {}", channel.getRemoteAddress());
                }
            }
        }
    }

    private static void debugRead(ByteBuffer buf) {
        ByteBufferUtil.debugRead(buf);
    }
}
